﻿/*
 * Erstellt mit SharpDevelop.
 * Benutzer: Ralph
 * Datum: 29.03.2009
 * Zeit: 17:19
 * 
 * Sie können diese Vorlage unter Extras > Optionen > Codeerstellung > Standardheader ändern.
 */
using System;
using System.Net.Sockets;
using System.Threading;
using LibSars;
namespace SarsClient
{
	/// <summary>
	/// PeerAcceptor class.
	/// Listens on sockets and
	/// adds new Peers via handshake.
	/// </summary>
	public class PeerAcceptor
	{
		#region Class members
		
		/// <summary>
		/// Acceptor running?
		/// </summary>
		bool isRunning = false;
		/// <summary>
		/// Underlaying TCP listener.
		/// </summary>
		TcpListener listener;
		/// <summary>
		/// Listening thread.
		/// </summary>
		Thread mainThread;
		/// <summary>
		/// Reference on connection manager
		/// to register new peers on it.
		/// </summary>
		ConnectionManager cmgr;
		/// <summary>
		/// Listening port.
		/// </summary>
		int port;
		
		#endregion
		
		#region Public methods
		
		/// <summary>
		/// Handles SARS handshake on socket.
		/// </summary>
		/// <param name="client">Socket to use.</param>
		public void HandleClient(Socket client){
			
			
			
			// Wait for incoming data
			Thread.Sleep(Global.SettingAcceptWait); 
			
			// Read in buffer
			byte[] buffer = new byte[1024];
			int recLen = client.Receive(buffer);
			
			// Extract SARS packets from buffer
			SarsPacket[] packets = SarsPacketByteArrayExtractor.GetAllPackets(buffer);
			
			// There must be more than 0 packets!
			if (packets.Length > 0){
				
				// Get first received packet
				SarsPacket inPkg = packets[0];
				
				// Compare if message type of packet is IMINURCHAT
				if (inPkg.Message.GetMTypeInt() == SarsPacketMessageIMINURCHAT.MTypeInt ){
					
					UInt16 senderId = inPkg.SenderId;
					
					// Create peer object
					Peer peer = new Peer(senderId, cmgr.OwnId, client);
					
					// Send own handshake packet
					SarsPacket outPkg = new SarsPacket();
					outPkg.Message = new SarsPacketMessageIMINURCHAT();
					outPkg.SenderId = cmgr.OwnId;
					outPkg.RecipientId = senderId;
					peer.SendPacket(outPkg);
					
					// Add to connection manager
					cmgr.AddPeer(peer);
					
					// Return to prevent socket close
					return ; 
				}
				
			}
			
			client.Close();
			
		}
		
		/// <summary>
		/// Main accepting loop for
		/// socket connections.
		/// </summary>
		void ListenerMain(){
			while(isRunning){
				try {
					Socket socket = listener.AcceptSocket();
					new Thread(delegate(){this.HandleClient(socket);}).Start();
				} catch { }
			}
		}
		

		
		
		public void Start(){
			
			if (isRunning)
				return;
			
			isRunning = true;
			
			listener = new TcpListener(System.Net.IPAddress.Any, port);
			mainThread = new Thread(delegate(){this.ListenerMain();});
			
			try {
				listener.Start();                        
				mainThread.Start();
			} catch {}
		}
		public void Stop(){
			
			if (!isRunning)
				return ;
			
			isRunning = false;
			
			listener.Stop();
			mainThread.Abort();
		}
		
		#endregion
		
		#region Constructors
		
		/// <summary>
		/// Creates listening Peer acceptor on port.
		/// </summary>
		/// <param name="p_cmgr">Reference on ConnectionManager for Peer management.</param>
		/// <param name="p_port">Port for connections.</param>
		public PeerAcceptor(ConnectionManager p_cmgr, int p_port){
			cmgr = p_cmgr;
			port = p_port;
		}
		
		#endregion
	}
}
